package com.client;

import java.util.ArrayList;

import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.SuggestOracle.Request;
import com.google.gwt.user.client.ui.SuggestOracle.Response;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.Query;
import com.google.gwt.visualization.client.QueryResponse;

public class TagOracle extends SuggestOracle {

	@Override
	public void requestSuggestions(Request request,
			com.google.gwt.user.client.ui.SuggestOracle.Callback callback) {
		if (-1 == request.getQuery().indexOf(32)) {
			String searchURL = CNStatsFront.baseURL + "querytagindex?words="
					+ request.getQuery();
//			CNStatsFront.get().showLoading(true);
			Query.create(URL.encode(searchURL)).send(
					new CBQueryTagIndex(request, callback, true));
		} else if (request.getQuery().length() > 1
				&& 32 == request.getQuery().charAt(request.getQuery().length() - 1)) {
			String searchURL = CNStatsFront.baseURL
					+ "querytag?direction=related&tag="
					+ request.getQuery().substring(0, request.getQuery().length() - 1);
			CNStatsFront.get().showLoading(true);
			Query.create(URL.encode(searchURL)).send(
					new CBQueryTagIndex(request, callback, false));
		}
	}

	@Override
	public boolean isDisplayStringHTML() {
		return true;
	}

}

final class TagSuggestion implements Suggestion {
	private String display;
	private String replacement;

	public TagSuggestion(String display, String replacement, String query) {
		this.display = display;
		this.replacement = replacement;
		this.boldQuery(query);
	}

	public String getDisplayString() {
		return display;
	}

	public String getReplacementString() {
		return replacement;
	}

	private void boldQuery(String query) {
		StringBuffer accum = new StringBuffer();

		int index = 0;
		int cursor = 0;
		while (true) {
			index = this.display.indexOf(query, index);
			if (index == -1) {
				break;
			}
			int endIndex = index + query.length();

			String part1 = this.display.substring(cursor, index);
			String part2 = this.display.substring(index, endIndex);
			cursor = endIndex;
			accum.append(part1).append("<strong>").append(part2).append("</strong>");

			index = endIndex;
		}
		accum.append(this.display.substring(cursor));
		this.display = accum.toString();
	}
}

final class CBQueryTagIndex implements
		com.google.gwt.visualization.client.Query.Callback {
	private Request request;
	private com.google.gwt.user.client.ui.SuggestOracle.Callback callback;
	private Boolean isIndex = true;

	public CBQueryTagIndex(Request request,
			com.google.gwt.user.client.ui.SuggestOracle.Callback callback,
			Boolean isIndex) {
		this.request = request;
		this.callback = callback;
		this.isIndex = isIndex;
	}

	public void onResponse(QueryResponse response) {
		CNStatsFront.get().showLoading(false);
		if (response.isError()) {
				CNStatsFront.get().showInfo(
						response.getMessage() + ":" + response.getDetailedMessage());
			return;
		} else {
			// Get the data from the QueryResponse.
			DataTable data = response.getDataTable();
			if (0 == data.getNumberOfRows() &&
					false == this.isIndex) {
				CNStatsFront.get().showInfo(CNStatsFront.get().constants.noMoreTags());
				return;
			}
			ArrayList<TagSuggestion> suggestions = new ArrayList<TagSuggestion>();
			for (int i = 0; i < data.getNumberOfRows(); i++) {
				String tag = data.getValueString(i, 0);
				if (false == this.isIndex) {
					tag = request.getQuery() + tag;
				}
				suggestions.add(new TagSuggestion(tag, tag, request.getQuery()));
			}
			Response resp = new Response(suggestions);
			callback.onSuggestionsReady(request, resp);
		}
	}
}
